<?php

/* 
 * Manager/VariableManager.php
 */
namespace RHX\Model\Manager;

use Zend\Db\Adapter\Adapter;
use RHX\Model\Table\EmployeTable;
use RHX\Model\Table\PeriodeTable;
use RHX\Model\Object\Employe;
use RHX\Model\Object\XRules;
use RHX\Helper\RHDateTime;
use RHX\Model\Object\Periode;
use RHX\Model\Object\Transfert;

class VariableManager{
    protected $adapter = null;
    
    /**
     * Constructeur
     * 
     * @param \Zend\Db\Adapter\Adapter $adapter
     */
    public function __construct(Adapter $adapter){
	$this->adapter=$adapter;
    }
    
    /**
     * Adapteur de base de données
     * 
     * @return Adapter
     */
    public function getAdapter(){
	return $this->adapter;
    }
    
    /**
     * Récupérer les employés d'un site à une période données
     * 
     * @param int $site
     * @param int $periode
     * @return array
     */
    public function getEmployeList($site, $periode){
	$sql = "SELECT e.*, po.libelle, po.code, s.libelle AS 'semaine_libelle', s.lundi, s.dimanche, p.libelle AS 'periode_libelle', pls.*, a.hebdo, a.taux "
		. "FROM rh_planning_semaine pls, rh_periode_semaine ps, rh_periode p, rh_semaine s, rh_avenant a, rh_poste po, rh_employe e "
		    ."WHERE pls.matricule = e.matricule
	    AND e.avenant_id = a.id
	    AND a.poste_id = po.id
	    AND pls.lundi = s.lundi
	    AND ps.semaine_id = s.id
	    AND ps.periode_id = p.id
	    AND e.site_id = $site
	    AND p.id = $periode
		ORDER BY e.matricule ASC, s.id ASC";
	    echo "<pre>$sql</pre>";
	$result = $this->getAdapter()
		->query($sql)
		->execute();
	$array = array();
	$employes = array();
	foreach($result as $row){
	    $employes[] = new Employe($this->getAdapter(), $row);
	    $array[] = $row;
	}
	
	return array(
	    'raw' => $array,
	    'employes' => $employes,
	);
    }
    
    /**
     * Liste des employés
     * 
     * @param int $siteId
     * @return Employe
     */
    public function getEmployes($siteId, $order ='matricule asc'){
	$tableEmploye = new EmployeTable($this->getAdapter());
	$employes = $tableEmploye->getEmployesBySiteEx2($siteId, $order);
	return $employes;
    }
    
   
    /**
     * Période
     * 
     * @param int $periodeId
     * @return \RHX\Model\Object\Periode
     */
    public function getPeriode($periodeId){
	$tablePeriode = new \RHX\Model\Table\PeriodeTable($this->getAdapter());
	return $tablePeriode->get($periodeId);
    }
    
    /**
     * 
     * @param int $matricule
     * @param int $periodeId
     * @return array
     */
    public function getEmployeStat($matricule, $periodeId){
	$planningManager = new PlanningManager($this->getAdapter());
	$statPeriode = $planningManager->summaryPeriod($planningManager->getEmploye($matricule), $this->getPeriode($periodeId));
	return $statPeriode;
    }
    
    /**
     * Récupérer les sommes d'une semaine
     * 
     * @param array $week
     * @return float
     */
    public function getSumInWeek($week){
	$total = 0.0;
	foreach($week as $day){
	    $total += $day->getDiff();
	}
	return $total;
    }
    
    /**
     * Détermine le Nombre de Code Entrée-Sortie
     * Si ce nombre est inférieur à 5 donc l'employé a travaillé durant cette semaine
     * Sinon cela indique que l'employé n'est pas encore présent sur le site
     * 
     * @param array $week
     * @return boolean
     */
    public function isCount($week){
	$es = 0;
	foreach($week as $day){
	    if($day->code == XRules::EntreeSortie){
		$es++;
	    }
	}
	if($es < 5){
	    return true;
	}
	return false;
    }
    
    /**
     * Récupérer l'occurence dans une semaine
     * 
     * @param int $code
     * @param array $week
     * @return int
     */
    public function getOccurenceInWeek($code, $week){
	$nb = 0;
	foreach($week as $day){
	    if($day->code == $code){
		$nb++;
	    }
	}
	return $nb;
    }
    
    /**
     * Récupérer l'occurence d'un code dans une période
     * 
     * @param int $code
     * @param array $periodeStat
     * @return int
     */
    public function getOccurenceInPeriode($code, $periodeStat){
	$nb = 0;
	foreach ($periodeStat as $week) {
	    $nb += $this->getOccurenceInWeek($code, $week);
	}
	return $nb;
    }
    
    /**
     * Heure d'un code pour une période
     * 
     * @param int $code
     * @param array $periodeStat
     * @return real
     */
    public function getHeureCodeInPeriode($code, $periodeStat){
	$h = 0.0;
	foreach($periodeStat as $week){
	    $h += $this->getHeureCodeInWeek($code, $week);
	}
	return $h;
    }
    
    /**
     * Heure d'un code pour une semaine
     * 
     * @param int $code
     * @param array $week
     * @return real
     */
    public function getHeureCodeInWeek($code, $week){
	$h = 0.0;
	foreach($week as $day){
	    if($day->code == $code){
		$h += $day->getDiff();
	    }
	}
	return $h;
    }
    
    /**
     * Occurence Retard et Absence dans une semaine donnée
     * 
     * @param array $semaine
     * @return int
     */
    public function getOccurenceRetardInWeek($semaine){
	$prda = $this->getOccurencePRDAInWeek($semaine);
	$abs = $this->getOccurenceInWeek(XRules::Absent, $semaine);
	$total = $prda + $abs;
	return $total;
    }
    
    /**
     * Temps Retard et Absence dans une semaine donnée
     * @param array $semaine
     * @return string
     */
    public function getTimeRetardInWeek($semaine){
	$total = new \RHX\Helper\RHDateTime();
	$total->setTime();
	foreach($semaine as $day){
	    if($day->code == XRules::ProblemeRetardDepartAnticipe){
		$total->addHours($day->getRetard(false), false);
		$total->addHours($day->getAnticipe(false), false);
	    }elseif ($day->code == XRules::Absent) {
		$total->addHours($day->getDiff(false), false);
	    }
	}
	return $total->totalHours();
    }
    
    /**
     * Occurence des retards et absences dans une période données
     * 
     * @param array $periodeStat
     * @return int
     */
    public function getOccurenceRetardInPeriode($periodeStat){
	$total = 0;
	foreach($periodeStat as $semaine){
	    $total += $this->getOccurenceRetardInWeek($semaine);
	}
	return $total;
    }
    
    /**
     * Temps des retards et absences dans une période
     * 
     * @param type $periodeStat
     * @return string
     */
    public function getTimeRetardInPeriode($periodeStat){
	$total= new \RHX\Helper\RHDateTime();
	$total->setTime();
	foreach($periodeStat as $semaine){
	    $total->addHours($this->getTimeRetardInWeek($semaine), false);
	}
	return $total->totalHours();
    }
    
    /**
     * Occurence des PRDA
     * 
     * @param array $semaine
     * @return int
     */
    public function getOccurencePRDAInWeek($semaine){
	$nb = 0;
	foreach ($semaine as $day){
	    if($day->code == XRules::ProblemeRetardDepartAnticipe){
		if($day->getRetard()){
		    $nb++;
		}
		if($day->getAnticipe()){
		    $nb++;
		}
	    }
	}
	return $nb;
    }
    
    /**
     * Détermine si l'employé entre en cours de mois ou pas
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param \RHX\Model\Object\Periode $periode
     * @return boolean
     */
    public function isEntreeMonth(Employe $employe, Periode $periode){
	$entree = new RHDateTime($employe->contrat_debut);
	$fin = new RHDateTime($periode->fin);
	$debut = new RHDateTime($fin->date('Y-m') .'-01');
	if($entree->isBetween($debut, $fin)){
	    return true;
	}
	return false;
    }
    
    /**
     * Détermine si l'employé quitte en cours de mois ou pas
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param \RHX\Model\Object\Periode $periode
     * @return boolean
     */
    public function isSortieMonth(Employe $employe, Periode $periode){
	$sortie = null;
	if($employe->contrat_fin == '0000-00-00' || $employe->contrat_fin == NULL){
	    $sortie = new RHDateTime();
	    $sortie->modify('next year');
	}else{
	    $sortie = new RHDateTime($employe->contrat_fin);
	}
	$fin = new RHDateTime($periode->fin);
	$mois = array(1 => 31, 2 => RHDateTime::isLeapYear((int)$fin->date('Y') ? 29 : 28), 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31);
	$finMois = new RHDateTime($fin->date('Y-m-' .$mois[(int)$fin->date('m')]));
	$debutMois = new RHDateTime($fin->date('Y-m') .'-01');
	if($sortie->isBetween($debutMois, $finMois)){
	    return true;
	}
	return false;
    }
    
    /**
     * Transfert Entrant de la période
     * 
     * @param int $periodeId
     * @param int $siteId
     * @return \RHX\Model\Object\Transfert
     */
    public function getTransfertEntrant($periodeId, $siteId){
	$tablePeriodeSemaine = new \RHX\Model\Table\PeriodeSemaineTable($this->getAdapter());
	$semaines = $tablePeriodeSemaine->getSemainesByPeriode($periodeId);
	$tableTransfert = new \RHX\Model\Table\TransfertTable($this->getAdapter());
	$transfertSemaines = array();
	foreach($semaines as $semaine){
	    $transfertSemaine = $tableTransfert->getTransfert($semaine->lundi, $siteId, \RHX\Model\Object\Transfert::Entrant);
	    if($transfertSemaine){
		$transfertSemaines[] = $transfertSemaine;
	    }
	}
	return $transfertSemaines;
    }
    
    /**
     * Grouper les transferts entrants par matricule employé
     * 
     * @param array $transfertSemaines
     * @return array
     */
    public function orderTransfert($transfertSemaines){
	$return = array();
	foreach ($transfertSemaines as $transferts){
	    foreach($transferts as $entrant){
		if(!isset($return[$entrant->matricule])){
		    $return[$entrant->matricule] = array();
		}
		$return[$entrant->matricule][] = $entrant;
	    }
	}
	return $return;
    }
    
    /**
     * Calcul d'une journée de transfert
     * 
     * @param \RHX\Model\Object\Transfert $entrant
     * @return \RHX\Model\Object\XData
     */
    public function calculateOneDayTransfert(Transfert $entrant){
	$calculator = new \RHX\Model\Object\XCalculator($this->getAdapter());
	$employe = $entrant->getEmploye();
	$dataCP = $employe->getDataCP();
	$data = $calculator->calculPresent($entrant->entree, $entrant->sortie, $entrant->pause, $entrant->repas, $dataCP['coef'], $dataCP['taux']);
	return $data;
    }
    
    /**
     * Numéro de la semaine à partir de la date
     * 
     * @param string $date
     * @return int
     */
    public function getSemaineNumber($date){
	$tableSemaine = new \RHX\Model\Table\SemaineTable($this->getAdapter());
	$semaine = $tableSemaine->select(function(\Zend\Db\Sql\Select $select)use($date){
	    $dayNames = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');
	    $where = new \Zend\Db\Sql\Where();
	    foreach($dayNames as $day){
		$where->OR->equalTo($day, $date);
	    }
	    $select->where($where);
	})->current();
	if($semaine){
	    $numero = sscanf($semaine->libelle, "Semaine %d");
	    return (int)$numero;
	}else{
	    return 0;
	}
    }
    
    /**
     * Valeur d'une semaine
     * 
     * @param array $week
     * @return real
     */
    public function getWeekValue($week){
	$total = 0.0;
	foreach ($week as $day){
	    $total += $day->getValue();
	}
	return $total;
    }
    
    
    /**
     * 
     * @param float $hebdo
     * @param int $planningId
     * @return real
     */
    public function getProrataHeureHebdomadaire($hebdo, $matricule, $semaine){
	$semaine = $this->getSemaineByDates($semaine);
	$planning = $this->getPlanning($matricule, $semaine->lundi);
	$dayName = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');
	$nbES = 0;
	foreach($dayName as $day){
	    $dayCode = $day .'_code';
	    if((int)$planning->$dayCode == XRules::EntreeSortie){
		$nbES++;
	    }
	}
	$prorata = $hebdo;
	if($nbES > 0){
	    if($nbES < 5){
		$prorata = $hebdo * ((5 - $nbES) / 5);
	    }elseif($nbES >= 5){
		$prorata = 0.0;
	    }
	}
	return $prorata;
    }
    
    /**
     * Semaines
     * 
     * @param int $semaineId
     * @return Semaine
     */
    public function getSemaine($semaineId){
	$tableSemaine = new \RHX\Model\Table\SemaineTable($this->adapter);
	return $tableSemaine->get($semaineId);
    }
    
    /**
     * Semaine
     * 
     * @param array $semaine
     * @return Semaine
     */
    public function getSemaineByDates($semaine){
	$day = NULL;
	foreach ($semaine as $d){
	    $day = $d;
	    break;
	}
	$tableSemaine = new \RHX\Model\Table\SemaineTable($this->getAdapter());
	return $tableSemaine->getSemaineByDate($day->date);
    }
    
    /**
     * Planning semaine
     * 
     * @param int $matricule
     * @param string $lundi
     * @return PlanningSemaine
     */
    public function getPlanning($matricule, $lundi){
	$tablePlanning = new \RHX\Model\Table\PlanningSemaineTable($this->adapter);
	$planning = $tablePlanning->getPlanningByDay($lundi, $matricule);
	return $planning;
    }

    
}

